package cn.zoujiedev.netty.core.decoder;

import cn.zoujiedev.netty.core.bean.Header;
import cn.zoujiedev.netty.core.bean.NettyMessage;
import cn.zoujiedev.netty.core.serialization.ObjectDecoder;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

/**
 * @Classname NettyMessageDecoder
 * @Description
 * @Date 2022-11-3 15:40
 * @Created by zoujie
 */
public class NettyMessageDecoder extends LengthFieldBasedFrameDecoder {

  private ObjectDecoder decoder;

  public NettyMessageDecoder(int maxFrameLength, int lengthFieldOffset, int lengthFieldLength, ObjectDecoder decoder) {
    super(maxFrameLength, lengthFieldOffset, lengthFieldLength,-8,0);
    this.decoder = decoder;
  }

  @Override
  protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
    ByteBuf buf = (ByteBuf) super.decode(ctx, in);
    if(buf == null){
      return null;
    }

    try {
      NettyMessage msg = new NettyMessage();

      //获取头部信息
      Header h = new Header();
      h.setCrcCode(buf.readInt());
      h.setLength(buf.readInt());
      h.setSessionId(buf.readLong());
      h.setType(buf.readByte());
      h.setPriority(buf.readByte());

      //获取attachment size
      int attachmentSize = buf.readInt();
      if(attachmentSize > 0){
        Map<String,Object> attach = new HashMap<>(attachmentSize);
        for (int i = 0; i < attachmentSize; i++) {
          int keySize = buf.readInt();
          byte[] keyBytes = new byte[keySize];

          buf.readBytes(keyBytes);

          String key = new String(keyBytes, StandardCharsets.UTF_8);
          Object value = decoder.decode(buf);
          attach.put(key,value);
        }

        h.setAttachment(attach);
      }

      if(buf.readableBytes() > 4){
        msg.setBody(decoder.decode(buf));
      }
      msg.setHeader(h);
      return msg;
    }finally {
      buf.release();
    }
  }
}
